package com.java.search.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.java.doc.ProductDoc;
import com.java.param.ProductSearchParam;
import com.java.pojo.Product;
import com.java.search.service.SearchService;
import com.java.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class SearchServiceImpl implements SearchService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;
    /**
     * 根据关键字和分页参数，进行es索引搜索，
     *1.判断关键字是否为空
     * 2.为空查询全部商品，不为空查询all字段
     * 3.设置分页参数
     * 4.查询es
     * 5.封装结果返回
     * @return 将结果封装到R中，返回商品服务
     * @param productSearchParam
     */
    @Override
    public R searchProduct(ProductSearchParam productSearchParam) {

        SearchRequest searchRequest = new SearchRequest("product");

        String search = productSearchParam.getSearch();
        if(StringUtils.isEmpty(search)){
            //为null，查询全部商品
            searchRequest.source().query(QueryBuilders.matchAllQuery());//查询全部数据
        }else{
            //不为空，对all字段查询
            searchRequest.source().query(QueryBuilders.matchQuery("all",productSearchParam.getSearch()));
        }
        //设置分页参数
        searchRequest.source().from((productSearchParam.getCurrentPage()-1)*productSearchParam.getPageSize());
        searchRequest.source().size(productSearchParam.getPageSize());
        //查询es
        SearchResponse searchResponse = null;
        try {
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException("查询错误！");
        }

        //结果集解析，获取其中需要用到的数据，total，product
        //获取hits数据
        SearchHits hits = searchResponse.getHits();

        //获取查询数据总量
        Long total = hits.getTotalHits().value;

        //获取存放主要信息的hits
        SearchHit[] hitsHits = hits.getHits();
        //jackson 用于json数据装成类对象
        ObjectMapper objectMapper = new ObjectMapper();

        List<Product> productList = new ArrayList<>();
        for (SearchHit hitsHit : hitsHits) {
            //查询的内容数据，对应的时ProductDoc模型时json数据，要进行转换
            String json = hitsHit.getSourceAsString();
            Product product = null;
            try {
                //添加jackson里的注解，忽略未对应的属性，all字段
                product = objectMapper.readValue(json, Product.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            productList.add(product);
        }
        //封装结果数据
        R ok = R.ok(null,productList,total);
        log.info("SearchServiceImpl.searchProduct 业务已经完成,结果:{}", ok);
        return ok;
    }

    /**
     * 商品同步：更新和添加
     *
     * @param product
     * @return
     */
    @Override
    public R save(Product product) throws IOException {
        //绑定索引表和插入id
        IndexRequest indexRequest = new IndexRequest("product").id(product.getProductId().toString());

        //转成productDoc对象，存all的
        ProductDoc productDoc = new ProductDoc(product);
        //json转换器
        ObjectMapper objectMapper = new ObjectMapper();

        String json = objectMapper.writeValueAsString(productDoc);
        //将json数据封装到indexRequest对象中
        indexRequest.source(json, XContentType.JSON);
        //插入es
        restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        return R.ok("数据同步成功！");
    }

    /**
     * 商品同步：删除
     *
     * @param productId
     * @return
     */
    @Override
    public R remove(Integer productId) throws IOException {

        DeleteRequest deleteRequest = new DeleteRequest("product");
        deleteRequest.id(productId.toString());
        //delete()根据文档删除,deleteByQuery()根据条件删除
        restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
        return R.ok("es库数据删除成功！");
    }
}
